const Coordinate = require('MathLib').Coordinate;
function CanvasPlus(canvas){
  this.canvas = canvas;
  ((/** Clone The Canvas */)=>{
    let cloneList = [
      , 'draw' , 'createLinearGradient'  , 'createCircularGradient'
      , 'createPattern'  , 'measureText'   , 'save'   , 'restore'
      , 'beginPath', 'moveTo', 'lineTo'
      , 'quadraticCurveTo', 'bezierCurveTo'
      , 'arc', 'rect', 'arcTo', 'clip', 'fillRect', 'strokeRect'
      , 'clearRect', 'fill'
      , 'stroke', 'closePath', 'scale', 'rotate', 'translate', 'drawImage'
      , 'strokeText'  , 'transform'
      , 'setTransform' , 'setFillStyle' , 'setStrokeStyle'  , 'setShadow', 'setGlobalAlpha'
      , 'setLineWidth'  , 'setLineJoin' , 'setLineCap' , 'setLineDash', 'setMiterLimit'
      , 'fillText'  , 'setFontSize'    , 'setTextAlign'   , 'setTextBaseline'
    ];
    for (let i = 0; i < cloneList.length; i++) {
      let _name = cloneList[i];
      if ((!this[_name]) && (_name !== undefined)) {
        try{
          this[_name] = (typeof canvas[_name] === 'function') ? canvas[_name].bind(canvas) : canvas[_name];
        } catch (igore) { console.log(igore)}
      }
    }
  })();
}
/*---------------------------------------------------------------------------------------*/
((/** Overwrite */)=>{
  /**
   * arcTo 取得一条曲线
   * @overwrite canvas.arcTo
   */
  function arcTo(e, t, n, r, o, a) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.arcTo(e.x, e.y, t.x, t.y, n, r);
    } else {
      canvas.arcTo(e, t, n, r, o, a);
    }
    return this;
  }
  CanvasPlus.prototype.arcTo = arcTo;

  /**
   * translate 取得一条曲线
   * @overwrite canvas.translate
   */
  function translate(e, t) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.translate(e.x, e.y);
    } else {
      canvas.translate(e, t);
    }
    return this;
  }
  CanvasPlus.prototype.translate = translate;
  
  /**
   * rotate 取得一条曲线
   * @overwrite canvas.rotate
   */
  function rotate(e) {
    let canvas = this.canvas;
    canvas.rotate(e);
    return this;
  }
  CanvasPlus.prototype.rotate = rotate;

  
  /**
   * clearRect 清除画布上在该矩形区域内的内容
   * @overwrite canvas.clearRect
   */
  function clearRect(e, t, w, d) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.clearRect(e.x, e.y, t, w);
    } else {
      canvas.clearRect(e, t, w, d);
    }
    return this;
  }
  CanvasPlus.prototype.clearRect = clearRect;

  /**
   * arc 取得一条圆弧
   * @overwrite canvas.arc
   */
  function arc(e, t, n, r, o, a) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.arc(e.x, e.y, t, n, r, o);
    } else {
      canvas.arc(e, t, n, r, o, a);
    }
    return this;
  }
  CanvasPlus.prototype.arc = arc;

  /**
   * moveTo 路径移动
   * @overwrite canvas.moveTo
   */
  function moveTo(e, t) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.moveTo(e.x, e.y);
    } else {
      canvas.moveTo(e, t);
    }
    return this;
  }
  CanvasPlus.prototype.moveTo = moveTo;


  /**
   * rect 创建一个矩形路径
   * @overwrite canvas.rect
   */
  function rect(e, t, w, d) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.rect(e.x, e.y, t, w);
    } else {
      canvas.rect(e, t, w, d);
    }
    return this;
  }
  CanvasPlus.prototype.rect = rect;
  /**
   * lineTo 画线条
   * @overwrite canvas.lineTo
   */
  function lineTo(e, t) {
    let canvas = this.canvas;
    if (typeof e === 'object' && !isNaN(e.x)) {
      canvas.lineTo(e.x, e.y);
    } else {
      canvas.lineTo(e, t);
    }
    return this;
  }
  CanvasPlus.prototype.lineTo = lineTo;

  /**
 * libezierCurveTo 画曲线
 * @overwrite canvas.lineTo
 */
  function libezierCurveTo(a , b, c ,d , e , t) {
    let canvas = this.canvas;
    if (typeof a === 'object' && !isNaN(e.x)) {
      canvas.libezierCurveTo(a.x, a.y, b.x, b.y, c.x, c.y);
    } else {
      canvas.libezierCurveTo(a, b, c, d, e, t);
    }
    return this;
  }
  CanvasPlus.prototype.libezierCurveTo = libezierCurveTo;

  /**
   * beginPath 创建一个路径
   * @overwrite canvas.beginPath
   */
  function beginPath() {
    let canvas = this.canvas;
    canvas.beginPath();
    return this;
  }
  CanvasPlus.prototype.beginPath = beginPath;

  /**
   * closePath 闭合一个路径
   * @overwrite canvas.closePath
   */
  function closePath() {
    let canvas = this.canvas;
    canvas.closePath();
    return this;
  }
  CanvasPlus.prototype.closePath = closePath;

  /**
   * clip 创建剪切空间
   * @overwrite canvas.clip
   */
  function clip() {
    let canvas = this.canvas;
    canvas.clip();
    return this;
  }
  CanvasPlus.prototype.clip = clip;

  /**
   * save 缓存上下文
   * @overwrite canvas.save
   */
  function save() {
    let canvas = this.canvas;
    canvas.save();
    return this;
  }
  CanvasPlus.prototype.save = save;

  /**
   * restore 恢复上下文
   * @overwrite canvas.restore
   */
  function restore() {
    let canvas = this.canvas;
    canvas.restore();
    return this;
  }
  CanvasPlus.prototype.restore = restore;

  /**
   * setFillStyle 设置填充样式
   * @overwrite canvas.setFillStyle
   */
  function setFillStyle(color) {
    let canvas = this.canvas;
    canvas.fillStyle = (color);
    return this;
  }
  CanvasPlus.prototype.setFillStyle = setFillStyle;

  /**
   * setStrokeStyle 设置描边样式
   * @overwrite canvas.setStrokeStyle
   */
  function setStrokeStyle(color) {
    let canvas = this.canvas;
    canvas.strokeStyle = color;
    return this;
  }
  CanvasPlus.prototype.setStrokeStyle = setStrokeStyle;

  /**
   * setShadowOffsetX 设置描边样式
   * @overwrite canvas.setShadowOffsetX
   */
  function setShadowOffsetX(s) {
    let canvas = this.canvas;
    canvas.shadowOffsetX = s;
    return this;
  }
  CanvasPlus.prototype.setShadowOffsetX = setShadowOffsetX;

  /**
   * setShadowColor 设置描边样式
   * @overwrite canvas.setShadowColor
   */
  function setShadowColor(s) {
    let canvas = this.canvas;
    canvas.shadowColor = s;
    return this;
  }
  CanvasPlus.prototype.setShadowColor = setShadowColor;
  /**
   * setShadowBlur
   * @overwrite canvas.setShadowBlur
   */
  function setShadowBlur(s) {
    let canvas = this.canvas;
    canvas.shadowBlur = s;
    return this;
  }
  CanvasPlus.prototype.setShadowBlur = setShadowBlur;
  /**
   * setShadowOffsetY 
   * @overwrite canvas.setShadowOffsetY
   */
  function setShadowOffsetY(s) {
    let canvas = this.canvas;
    canvas.shadowOffsetY = s;
    return this;
  }
  CanvasPlus.prototype.setShadowOffsetY = setShadowOffsetY;

  /**
   * setLineWidth
   * @overwrite canvas.setLineWidth
   */
  function setLineWidth(s) {
    let canvas = this.canvas;
    canvas.setLineWidth(s);
    return this;
  }
  CanvasPlus.prototype.setLineWidth = setLineWidth;
  /**
   * setLineCap
   * @overwrite canvas.setLineCap
   */
  function setLineCap(s) {
    let canvas = this.canvas;
    canvas.setLineCap(s);
    return this;
  }
  CanvasPlus.prototype.setLineCap = setLineCap;
  /**
   * setLineJoin
   * @overwrite canvas.setLineJoin
   */
  function setLineJoin(s) {
    let canvas = this.canvas;
    canvas.setLineJoin(s);
    return this;
  }
  CanvasPlus.prototype.setLineJoin = setLineJoin;

  /**
   * setMiterLimit
   * @overwrite canvas.setMiterLimit
   */
  function setMiterLimit(s) {
    let canvas = this.canvas;
    canvas.setMiterLimit(s);
    return this;
  }
  CanvasPlus.prototype.setMiterLimit = setMiterLimit;
  /**
   * setMiterLimit
   * @overwrite canvas.setMiterLimit
   */
  function setMiterLimit(s) {
    let canvas = this.canvas;
    canvas.setMiterLimit(s);
    return this;
  }
  CanvasPlus.prototype.setMiterLimit = setMiterLimit;
  /**
   * setGlobalCompositeOperation
   * @overwrite canvas.setGlobalCompositeOperation
   */
  function setGlobalCompositeOperation(s) {
    let canvas = this.canvas;
    canvas.globalCompositeOperation = (s);
    return this;
  }
  CanvasPlus.prototype.setGlobalCompositeOperation = setGlobalCompositeOperation;  
  /**
   * setGlobalAlpha
   * @overwrite canvas.setGlobalAlpha
   */
  function setGlobalAlpha(s) {
    let canvas = this.canvas;
    canvas.globalAlpha = (s);
    return this;
  }
  CanvasPlus.prototype.setGlobalAlpha = setGlobalAlpha;
  /**
   * setFont
   * @overwrite canvas.setFont
   */
  function setFont(s) {
    let canvas = this.canvas;
    canvas.font = (s);
    return this;
  }
  CanvasPlus.prototype.setFont = setFont;
  /**
   * setLineDashOffset
   * @overwrite canvas.setLineDashOffset
   */
  function setLineDashOffset(s) {
    let canvas = this.canvas;
    canvas.lineDashOffset = (s);
    return this;
  }
  CanvasPlus.prototype.setLineDashOffset = setLineDashOffset;

  
  /**
   * drawImage 填充样式
   * @overwrite canvas.drawImage
   */
  function drawImage(src,a,b,c,d,e,f,g,h) {
    let canvas = this.canvas, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight;
    if (typeof a === 'object' && !isNaN(a.x)) {
      sx = a.x;
      sy = a.y;
      sWidth = b;
      sHeight = c;
      dx = d.x;
      dy = d.y;
      dWidth = e;
      dHeight = f;
    } else {
      sx = a;
      sy = b;
      sWidth = c;
      sHeight = d;
      dx = e;
      dy = f;
      dWidth = g;
      dHeight = h;
    }
    canvas.drawImage(src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    return this;
  }
  CanvasPlus.prototype.drawImage = drawImage;
  /**
   * fill 填充样式
   * @overwrite canvas.fill
   */
  function fill(color, rule) {
    let canvas = this.canvas;
    if (color && color !== "evenodd" ) {
      this.save().setFillStyle(color).fill(rule ? rule : null).restore();
    } else if (color === "evenodd") {
      canvas.fill('evenodd');
    } else {
      canvas.fill();
    }
    return this;
  }
  CanvasPlus.prototype.fill = fill;

  /**
   * stroke 描边
   * @overwrite canvas.fill
   */
  function stroke(color) {
    let canvas = this.canvas;
    if (color) {
      canvas.save()
      canvas.setStrokeStyle(color);
      canvas.stroke();
      canvas.restore();
    } else {
      canvas.stroke();
    }
    return this;
  }
  CanvasPlus.prototype.stroke = stroke;

  /**
   * setTextBaseline 设置文字的竖直对齐
   * @overwrite canvas.setTextBaseline
   */
  function setTextBaseline(t) {
    let canvas = this.canvas;
    canvas.setTextBaseline(t);
    return this;
  }
  CanvasPlus.prototype.setTextBaseline = setTextBaseline;

  /**
   * setTextAlign 设置文字的对齐
   * @overwrite canvas.setTextAlign
   */
  function setTextAlign(t) {
    let canvas = this.canvas;
    canvas.setTextAlign(t)
    return this;
  }
  CanvasPlus.prototype.setTextAlign = setTextAlign;

  /**
   * setFontSize 设置字体的字号
   * @overwrite canvas.setFontSize
   */
  function setFontSize(n) {
    let canvas = this.canvas;
    canvas.setFontSize(n)
    return this;
  }
  CanvasPlus.prototype.setFontSize = setFontSize;

  /**
   * fillText 在画布上绘制被填充的文本
   * @overwrite canvas.fillText
   */
  function fillText(t, a, b, c) {
    let canvas = this.canvas, x, y, maxWidth;
    if (typeof a === 'object' && !isNaN(a.x)) {
      x = a.x;
      y = a.y;
      maxWidth = b;
    } else {
      x = a;
      y = b;
      maxWidth = c;
    }
    canvas.fillText(t, x, y, maxWidth)
    return this;
  }
  CanvasPlus.prototype.fillText = fillText;
})();
/*---------------------------------------------------------------------------------------*/
/**
 * arcRect 创建一个圆角矩形路径 xy w h r
 */
function arcRect(a,b,c,d,e) {
  let canvas = this.canvas, x, y, w, h, r;
  if (typeof a === 'object' && !isNaN(a.x)) {
    x = a.x; 
    y = a.y;
    w = b;
    h = c;
    r = d;
  } else {
    x = a;
    y = b;
    w = c;
    h = d;
    r = e;
  }
  ((x, y, w, h, r) => {
    if (w < 2 * r) { r = w / 2; }
    if (h < 2 * r) { r = h / 2; }
    this.beginPath()
      .moveTo(x + r, y)
      .arcTo(x + w, y, x + w, y + h, r)
      .arcTo(x + w, y + h, x, y + h, r)
      .arcTo(x, y + h, x, y, r)
      .arcTo(x, y, x + w, y, r)
      .closePath();
  })(x, y, w, h, r)
  return this;
}
CanvasPlus.prototype.arcRect = arcRect;

/**
 * fiilLinesText 填充多行文字
 */
function fiilLinesText(text, a, b, c, d){
  let canvas = this.canvas, x, y, lineHeight, lineWidth, accumulator = 0, lastSubStrIndex = 0, lastY;
  if (typeof a === 'object' && !isNaN(a.x)) {
    x = a.x;
    y = a.y;
    lineWidth = b;
    lineHeight = c;
  } else {
    x = a;
    y = b;
    lineWidth = c;
    lineHeight = d;
  }
  (()=>{
    lastY = y;
    for (let i = 0; i < text.length; i++) {
      accumulator += canvas.measureText(text[i]).width;
      if (accumulator > lineWidth) {
        i--;accumulator = 0;
        let clipText = text.substring(lastSubStrIndex, i + 1);
        lastSubStrIndex = i+1;
        canvas.fillText(clipText, x, lastY);
        lastY += lineHeight;
      }
      if (i === text.length-1) {
        let clipText = text.substring(lastSubStrIndex, i + 1);
        canvas.fillText(clipText, x, lastY);
      }
    }
  })();
  return this;
}
CanvasPlus.prototype.fiilLinesText = fiilLinesText;

/**
 * circle 创建一个圆形路径 xy r
 */
function circle(a, b, c, d, e) {
  let canvas = this.canvas, x, y, r, o;
  if (typeof a === 'object' && !isNaN(a.x)) {
    x = a.x;
    y = a.y;
    r = b;
    o = c;
  } else {
    x = a;
    y = b;
    r = c;
    o = d;
  }
  if(!e){ this.beginPath() }
  this.arc(x, y, r, 0, Math.PI *2, o);
  if (!e) {this.closePath()}
  return this;
}
CanvasPlus.prototype.circle = circle;

module.exports.CanvasPlus = CanvasPlus;